View Javadoc

1   /***
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Exoffice Technologies.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Exoffice Technologies. Exolab is a registered
23   *    trademark of Exoffice Technologies.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2004-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: ManagedConnectionHandle.java,v 1.8 2006/12/16 12:37:17 tanderson Exp $
44   */
45  package org.exolab.jms.net.connector;
46  
47  import org.exolab.jms.net.uri.URI;
48  
49  import java.security.Principal;
50  
51  
52  /***
53   * A handle to a {@link ManagedConnection} that tracks its utilisation.
54   *
55   * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
56   * @version $Revision: 1.8 $ $Date: 2006/12/16 12:37:17 $
57   */
58  final class ManagedConnectionHandle implements ManagedConnection {
59  
60      /***
61       * The connection pool that owns this.
62       */
63      private final DefaultConnectionPool _pool;
64  
65      /***
66       * The connection to delegate all requests to.
67       */
68      private final ManagedConnection _connection;
69  
70      /***
71       * The connection factory for resolving connections via their URI.
72       */
73      private final ConnectionFactory _resolver;
74  
75      /***
76       * The no. of active ConnectionHandle instances.
77       */
78      private int _connectionCount = 0;
79  
80      /***
81       * Determines if the connection has been since {@link #clearUsed} was
82       * last invoked.
83       */
84      private boolean _used = false;
85  
86      /***
87       * Determines if a ping is in progress.
88       */
89      private boolean _pinging = false;
90  
91      /***
92       * The no. of times {@link #incPingWaits} has been invoked since the last
93       * {@link #ping}.
94       */
95      private int _pingWaits;
96  
97  
98      /***
99       * Construct a new <code>ManagedConnectionHandle</code>.
100      *
101      * @param pool       the pool that owns this
102      * @param connection the connection to delegate requests to
103      * @param resolver   the connection factory for resolving connections via
104      *                   their URI.
105      */
106     public ManagedConnectionHandle(DefaultConnectionPool pool,
107                                    ManagedConnection connection,
108                                    ConnectionFactory resolver) {
109         _pool = pool;
110         _connection = connection;
111         _resolver = resolver;
112     }
113 
114     /***
115      * Registers a handler for handling invocations on objects exported via this
116      * connection. Once a handler is registered, it cannot be de-registered.
117      *
118      * @param handler the invocation handler
119      * @throws IllegalStateException if a handler is already registered
120      * @throws ResourceException     for any error
121      */
122     public void setInvocationHandler(InvocationHandler handler)
123             throws ResourceException {
124         _connection.setInvocationHandler(handler);
125     }
126 
127     /***
128      * Registers a connection event listener.
129      *
130      * @param listener the connection event listener
131      * @throws ResourceException for any error
132      */
133     public void setConnectionEventListener(ManagedConnectionListener listener)
134             throws ResourceException {
135         _connection.setConnectionEventListener(listener);
136     }
137 
138     /***
139      * Creates a new connection handle for the underlying physical connection.
140      *
141      * @return a new connection handle
142      * @throws IllegalStateException if an <code>InvocationHandler</code> hasn't
143      *                               been registered
144      * @throws ResourceException     for any error
145      */
146     public Connection getConnection() throws ResourceException {
147         Connection connection = _connection.getConnection();
148         return new ConnectionHandle(connection);
149     }
150 
151     /***
152      * Ping the connection. The connection event listener will be notified
153      * if the ping succeeds.
154      *
155      * @throws ResourceException for any error
156      */
157     public synchronized void ping() throws ResourceException {
158         try {
159             _pinging = true;
160             _pingWaits = 0;
161             _connection.ping();
162         } catch (ResourceException exception) {
163             _pinging = false;
164             throw exception;
165         }
166     }
167 
168     /***
169      * Determines if a ping has been sent.
170      *
171      * @return <code>true</code> if a ping has been sent
172      */
173     public synchronized boolean pinging() {
174         return _pinging;
175     }
176 
177     /***
178      * Notifies of a ping response.
179      * Clears the ping status, and resets the ping wait to <code>0</code>.
180      */
181     public synchronized void pinged() {
182         _pinging = false;
183         _pingWaits = 0;
184     }
185 
186     /***
187      * Increments the no. of times this connection has waited for a ping
188      * response.
189      *
190      * @return the no. of times this connection has waited for a ping response
191      */
192     public synchronized int incPingWaits() {
193         return ++_pingWaits;
194     }
195 
196     /***
197      * Returns the remote address to which this is connected.
198      *
199      * @return the remote address to which this is connected
200      * @throws ResourceException for any error
201      */
202     public URI getRemoteURI() throws ResourceException {
203         return _connection.getRemoteURI();
204     }
205 
206     /***
207      * Returns the local address that this connection is bound to.
208      *
209      * @return the local address that this connection is bound to
210      * @throws ResourceException for any error
211      */
212     public URI getLocalURI() throws ResourceException {
213         return _connection.getLocalURI();
214     }
215 
216     /***
217      * Returns the principal associated with this connection.
218      *
219      * @return the principal associated with this connection,
220      *         or <code>null<code> if none is set
221      * @throws ResourceException for any error
222      */
223     public Principal getPrincipal() throws ResourceException {
224         return _connection.getPrincipal();
225     }
226 
227     /***
228      * Destroys the physical connection.
229      *
230      * @throws ResourceException for any error
231      */
232     public void destroy() throws ResourceException {
233         _connection.destroy();
234     }
235 
236     /***
237      * Marks the connection as being used.
238      */
239     public synchronized void setUsed() {
240         _used = true;
241     }
242 
243     /***
244      * Determines if the connection has been used since {@link #clearUsed}
245      * was last invoked.
246      */
247     public synchronized boolean used() {
248         return _used;
249     }
250 
251     /***
252      * Marks the connection as being unused.
253      */
254     public synchronized void clearUsed() {
255         _used = false;
256     }
257 
258     /***
259      * Determines if the connection can be destroyed. The connection
260      * can be destroyed if there are no associated {@link Connection} instances,
261      * and it has been used since {@link #clearUsed} was invoked.
262      *
263      * @return <code>true</code> if the connection may be destroyed
264      */
265     public synchronized boolean canDestroy() {
266         return (_connectionCount == 0) && (!_used);
267     }
268 
269     /***
270      * Increment the no. of references to this connection.
271      */
272     private synchronized void incActiveConnections() {
273         ++_connectionCount;
274     }
275 
276     /***
277      * Decrement the no. of references to this connection.
278      */
279     private synchronized void decActiveConnections() {
280         --_connectionCount;
281         if (_connectionCount <= 0) {
282             _pool.idle(this);
283         }
284     }
285 
286     public boolean usedSinceLastPing() {
287         return false;  //To change body of created methods use File | Settings | File Templates.
288     }
289 
290     /***
291      * Helper class reference count a {@link Connection} instance.
292      */
293     private class ConnectionHandle implements Connection {
294 
295         /***
296          * The connection to delegate all requests to.
297          */
298         private Connection _connection;
299 
300         /***
301          * Construct a new <code>ConnectionHandle</code>.
302          *
303          * @param connection the connection to delegate requests to
304          */
305         public ConnectionHandle(Connection connection) {
306             _connection = connection;
307             incActiveConnections();
308         }
309 
310         /***
311          * Invoke a method on a remote object.
312          *
313          * @param request the request
314          * @return the result of the invocation
315          * @throws Throwable for any transport error
316          */
317         public Response invoke(Request request) throws Throwable {
318             Response response = null;
319             setUsed();
320             try {
321                 ConnectionContext.push(getPrincipal(), _resolver);
322                 response = _connection.invoke(request);
323             } finally {
324                 ConnectionContext.pop();
325             }
326             return response;
327         }
328 
329         /***
330          * Returns the remote address to which this is connected.
331          *
332          * @return the remote address to which this is connected
333          * @throws ResourceException for any error
334          */
335         public URI getRemoteURI() throws ResourceException {
336             return _connection.getRemoteURI();
337         }
338 
339         /***
340          * Returns the local address that this connection is bound to.
341          *
342          * @return the local address that this connection is bound to
343          * @throws ResourceException for any error
344          */
345         public URI getLocalURI() throws ResourceException {
346             return _connection.getLocalURI();
347         }
348 
349         /***
350          * Close this connection, releasing any allocated resources.
351          *
352          * @throws ResourceException for any error.
353          */
354         public void close() throws ResourceException {
355             try {
356                 _connection.close();
357             } finally {
358                 _connection = null;
359                 decActiveConnections();
360             }
361         }
362 
363         /***
364          * Called by the garbage collector when there are no more references to
365          * the object.
366          */
367         protected void finalize() throws Throwable {
368             if (_connection != null) {
369                 decActiveConnections();
370             }
371             super.finalize();
372         }
373     }
374 }